package com.chang.product.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chang.common.utils.PageUtils;
import com.chang.common.utils.Query;
import com.chang.product.dto.AttrGroupWithAttrsVo;
import com.chang.product.entity.AttrEntity;
import com.chang.product.entity.AttrGroupEntity;
import com.chang.product.mapper.AttrGroupDao;
import com.chang.product.service.AttrAttrgroupRelationService;
import com.chang.product.service.AttrGroupService;
import com.chang.product.service.AttrService;
import com.chang.product.service.ProductAttrValueService;
import com.chang.product.vo.SpuItemAttrGroupVo;
import jakarta.annotation.Resource;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;


@Service("attrGroupService")
public class AttrGroupServiceImpl extends ServiceImpl<AttrGroupDao, AttrGroupEntity> implements AttrGroupService {

    @Lazy
    @Autowired
    AttrService attrService;

    @Resource
    AttrAttrgroupRelationService attrGroupRelationService;

    @Resource
    ProductAttrValueService productAttrValueService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<AttrGroupEntity> page = this.page(
                new Query<AttrGroupEntity>().getPage(params),
                new QueryWrapper<>()
        );
        return new PageUtils(page);
    }

    /*
     * @Author Chang
     * @Date 2024/3/5 14:34
     * @Description 查询商品属性的时候必须选择一个商品,然后再进行模糊匹配,如果没有选择就查询全部,根据id是否为默认值0来判断
     * @Param [params, categoryId]
     * @Return com.chang.common.utils.PageUtils
     * @Since version 1.0
     */
    @Override
    public PageUtils queryPage(Map<String, Object> params, Long categoryId) {
        String key = (String) params.get("key"); // 这个key是前端传递用来匹配字段的,但是可能匹配多个字段,如果是数字就对应id,字符就模糊匹配组名
        LambdaQueryWrapper<AttrGroupEntity> queryWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.hasLength(key)) {
            queryWrapper.and((obj) -> {
                obj.eq(AttrGroupEntity::getAttrGroupId, key)
                        .or()
                        .like(AttrGroupEntity::getAttrGroupName, key);
            });
        }
        if (categoryId == 0) { // 如果id为0,则说明是查询全部  前端id初始化值为0 this.page方法的第一个参数IPage对象使用query工具类进行生成
            IPage<AttrGroupEntity> page = this.page(new Query<AttrGroupEntity>().getPage(params), queryWrapper);
            return new PageUtils(page);
        } else {
            queryWrapper.eq(AttrGroupEntity::getCatelogId, categoryId);
            IPage<AttrGroupEntity> page = this.page(new Query<AttrGroupEntity>().getPage(params), queryWrapper);
            return new PageUtils(page);
        }
    }

    /*
     * @Author Chang
     * @Date 2024/3/19 16:08
     * @Description 根据分类id查出该分类下所有的属性分组及分组中的属性
     * @Param [catelogId]
     * @Return java.util.List<com.chang.product.dto.AttrGroupWithAttrsVo>
     * @Since version 1.0
     */
    @Override
    public List<AttrGroupWithAttrsVo> getAttrGroupWithAttrsByCatelogId(Long catelogId) {
        List<AttrGroupWithAttrsVo> AttrGroupWithAttrsVolist = new ArrayList<>();

        // 根据三级分类id获取属性分组集合
        List<AttrGroupEntity> attrGroupEntities = baseMapper.selectList(new LambdaQueryWrapper<AttrGroupEntity>()
                .eq(AttrGroupEntity::getCatelogId, catelogId));

        // 根据属性分组id获取每一个分组的属性
        attrGroupEntities.forEach((item) -> {
            AttrGroupWithAttrsVo attrGroupWithAttrsVo = new AttrGroupWithAttrsVo();
            // 将属性分组的属性添加到封装类中
            BeanUtils.copyProperties(item, attrGroupWithAttrsVo);
            // 在attrServiceImpl中已经声明过一个使用属性分组id获取分组下所有属性的方法,这里直接调用
            List<AttrEntity> attrlist = attrService.getRelationAttr(item.getAttrGroupId());
            // 将属性分组下的属性集合添加进封装类
            attrGroupWithAttrsVo.setAttrs(attrlist);
            AttrGroupWithAttrsVolist.add(attrGroupWithAttrsVo);
        });


        return AttrGroupWithAttrsVolist;
    }

    /**
     * @param: [spuId, catalogId]
     * @return: java.util.List<com.chang.product.vo.SpuItemAttrGroupVo>
     * @author changzhenxi
     * @date 2024/11/13 - 17:51
     * @history 2024/11/13 - 17:51 changzhenxi create   这里的数据库我感觉很恶心,属性分组是一个表,属性又是一个表,属性值又是一个表。然后又搞了专门的两个表来进行关联
     * 最搞笑的是最后由于冗余字段足够,甚至可以跳过attr表直接关联 属性值表和属性分组表 如下:
     * select
     * ag.attr_group_name,
     * aar.attr_id,
     * av.attr_name,
     * av.attr_value,
     * av.spu_id
     * from pms_attr_group ag
     * left join pms_attr_attrgroup_relation aar on aar.attr_group_id  = ag.attr_group_id
     * left join pms_product_attr_value av on av.attr_id  = aar.attr_id
     * WHERE
     * av.spu_id  = 26;
     * <p>
     * 正常查sql需要用到左连接,但是我尝试直接用代码解决,其中list转map之后的key就是左连接的条件字段
     * 这里的数据结构为 属性分组中包含多个属性,属性中又包含多个属性值
     * 所以最后遍历封装的时候按照属性分组往下细分的顺序封装 将更细的数据封装为map,方便赋值
     */
    @Override
    public List<SpuItemAttrGroupVo> getAttrGroupWithAttrsBySpuId(Long spuId, Long catalogId) {

        /*List<SpuItemAttrGroupVo> spuItemAttrGroupVos = new ArrayList<>();

        // pms_product_attr_value 用来关联商品属性和属性值的表
        List<ProductAttrValueEntity> attrValueEntityList = productAttrValueService.getBaseMapper().selectList(new LambdaQueryWrapper<ProductAttrValueEntity>().eq(ProductAttrValueEntity::getSpuId, spuId));
        Map<Long, String> attrValueMap = attrValueEntityList.stream().collect(Collectors.toMap(ProductAttrValueEntity::getAttrId, ProductAttrValueEntity::getAttrValue));

        // 首先获取所有三级分类需要的属性分组信息
        List<AttrGroupEntity> attrGroupEntities = baseMapper.selectList(new LambdaQueryWrapper<AttrGroupEntity>().eq(AttrGroupEntity::getCatelogId, catalogId));
        Map<Long, AttrGroupEntity> AttrGroupMap = attrGroupEntities.stream().collect(Collectors.toMap(AttrGroupEntity::getAttrGroupId, item -> item));

        // 这里先拿到属性分组id集合 和属性id集合
        List<Long> attrGroupIds =  new ArrayList<>();
        attrGroupEntities.forEach((item) -> {attrGroupIds.add(item.getAttrGroupId());});

        //然后拿着分组id一次性查询所有关联表中的分组属性 这个关联表总共就三个字段,所以干脆全部获取了 然后进行拼装, 目的是不在循环内根据属性分组id直接查库,减小数据库压力
        List<AttrAttrgroupRelationEntity> attrAttrgroupRelationEntities = attrGroupRelationService.getBaseMapper().selectList(new LambdaQueryWrapper<AttrAttrgroupRelationEntity>().in(AttrAttrgroupRelationEntity::getAttrGroupId, attrGroupIds));

        // 拿着关联表中的数据获取属性分组所需的属性id  然后拿着属性id批量查询所有属性分组需要的属性
        List<Long> attrIds =  new ArrayList<>();
        attrAttrgroupRelationEntities.forEach((item) -> {attrIds.add(item.getAttrId());});
        List<AttrEntity> attrEntities = attrService.getBaseMapper().selectList(new LambdaQueryWrapper<AttrEntity>().in(AttrEntity::getAttrId, attrIds));
        Map<Long, AttrEntity> AttrMap = attrEntities.stream().collect(Collectors.toMap(AttrEntity::getAttrId, item -> item));

        // 这里比较复杂,因为是关联表中存在多条数据是同一个分组id的情况, pms_attr_attrgroup_relation
        attrAttrgroupRelationEntities.forEach((item) -> {
            SpuItemAttrGroupVo spuItemAttrGroupVo = new SpuItemAttrGroupVo();
            // 首先获取分组信息 封装分组名称
            AttrGroupEntity attrGroupEntity = AttrGroupMap.get(item.getAttrGroupId());
            spuItemAttrGroupVo.setGroupName(attrGroupEntity.getAttrGroupName());
            // 创建属性集合
            List<Attr> attrList = new ArrayList<>();
            // 筛选出此次循环中需要用到的所有分组下的属性集合
            List<AttrAttrgroupRelationEntity> filteLlist = attrAttrgroupRelationEntities.stream().filter(item1 -> item1.getAttrGroupId().equals(attrGroupEntity.getAttrGroupId())).toList();

            // 得到所有分组下的属性之后就开始封装
            filteLlist.forEach(item2->{
                Attr attr = new Attr();
                AttrEntity attrEntity = AttrMap.get(item2.getAttrId());
                attr.setAttrId(attrEntity.getAttrId());
                attr.setAttrName(attrEntity.getAttrName());
                attr.setAttrValue(attrValueMap.get(item2.getAttrId()));
                attrList.add(attr);
            });
            // 封装分组属性集合
            spuItemAttrGroupVo.setAttrs(attrList);
            // 最后统一封装VO对象
            spuItemAttrGroupVos.add(spuItemAttrGroupVo);
        });*/

        List<SpuItemAttrGroupVo> spuItemAttrGroupVos = baseMapper.getAttrGroupWithAttrsBySpuId(spuId);


        return spuItemAttrGroupVos;
    }
}